#include <string.h>

#include "lib.h"

#include "djpkguts.h"
#include "shue.h"
#include "vphand.h"
#include "cardmgr.h"

#include "pte_djpk.h"	// PTE_xxx -> PayTableEvents...i.e. VPEVT_xxx

static CardMgr stdMgr;

Shue*
DoubleJackpotPokerGuts::newShue(const ShueGameInfo &sgi)
{
	return new Shue(&stdMgr, 1, sgi);
}

CardMgr*
DoubleJackpotPokerGuts::getCardMgr()
{
	return &stdMgr;
}

int32
DoubleJackpotPokerGuts::CalcPayout(int32* pEvent, VPHand* pHand, int32 Bet,
	CalcPayoutMode, uint8* subGameData, int32 length)
{
	*pEvent = classifyHand(pHand);

	return *pEvent != VPEVT_LOSER ? PTBLENTRY(Bet-1, *pEvent) : 0;
}

int32
DoubleJackpotPokerGuts::classifyHand(VPHand* pHand)
{
	uint8 counts[13];
	int32 i, rank;
	uint8* probe, *first;
	bool8 flush = true;

	if (!pHand || (pHand && pHand->getCount() != 5))
		return VPEVT_LOSER;

	memset(counts, 0, 13);	// 2:index 0, 3:index 1 ... A:index 12

	for (i = 0 ; i < pHand->getCount(); i++)
	{
		++counts[stdMgr.getRank(pHand->getCardAt(i)) - 2];

		if (i > 0 && flush)
			flush = (bool8)(stdMgr.getSuit(pHand->getCardAt(i)) ==
				stdMgr.getSuit(pHand->getCardAt(i - 1)));
	}

	// pair, 2 pairs, 3-of-a-kind, 4-of-a-kind, full house
	//
	probe = (uint8*)memchr(counts, 4, 13);
	if (probe)
	{
		first = (uint8*)memchr(counts, 1, 13);
		if (!first)
			return VPEVT_LOSER;		// "shouldn't" happen
		rank = first - counts + 2;

		switch (probe - counts + 2)
		{
			case CardMgr::ACE:
				if (rank >= CardMgr::JACK && rank <= CardMgr::KING)
					return VPEVT_4OFAKIND_ACES_WITH_K_Q_J;
				else
					return VPEVT_4OFAKIND_ACES;

			case CardMgr::KING:
			case CardMgr::QUEEN:
			case CardMgr::JACK:
				if ((rank >= CardMgr::JACK && rank <= CardMgr::KING) ||
					rank == CardMgr::ACE)
					return VPEVT_4OFAKIND_K_Q_J_WITH_ACE_K_Q_J;
				else
					return VPEVT_4OFAKIND_K_Q_J;

			default:
				return VPEVT_4OFAKIND_2_THRU_10;
		}
	}

	if (memchr(counts, 3, 13))
		if (memchr(counts, 2, 13))
			return VPEVT_FULLHOUSE;
		else
			return VPEVT_3OFAKIND;

	probe = (uint8*)memchr(counts, 2, 13);
	if (probe)
	{
		if (probe < counts+(13-1) && memchr(probe+1, 2, 13 - (probe-counts+1)))
			return VPEVT_2PAIR;
		else if (probe - counts >= minPair-2)
			return VPEVT_XXX_OR_BETTER;
	}

	// straights
	//
	first = probe = (uint8*)memchr(counts, 1, 13);
	i = 0;
	while (probe < counts + 13)
		if (*probe++ == 1)
			i++;
		else
			break;

	if (i == 5)
	{
		if (flush)
			if (first == counts + 10-2)
				return VPEVT_ROYALFLUSH;
			else
				return VPEVT_STRAIGHTFLUSH;

		return VPEVT_STRAIGHT;
	}

	if (i == 4 &&								// ace-low straights
		counts[CardMgr::ACE-2] && first == counts)
	{
		if (flush)
			return VPEVT_STRAIGHTFLUSH;

		return VPEVT_STRAIGHT;
	}

	return flush ? VPEVT_FLUSH : VPEVT_LOSER;
}
